use std::borrow::Borrow;

///
/// @ProjectName:    learning_rust
/// @Description:    
/// @File:           jz58.rs
/// @Author:         wujehy
/// @Email:          wujehy@qq.com
/// @Time:           2021-07-04 00:03
///
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Box<TreeNode>>,
    pub right: Option<Box<TreeNode>>,
}

impl TreeNode {
    #[inline]
    fn new(val: i32) -> Self {
        TreeNode {
            val: val,
            left: None,
            right: None,
        }
    }
}


struct Solution {}

impl Solution {
    fn new() -> Self {
        Solution {}
    }

    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     * @param pRoot TreeNode类
     * @return bool布尔型
     */
    pub fn isSymmetrical(&self, pRoot: Option<Box<TreeNode>>) -> bool {
        // write code here
        let (l , r ) = match pRoot {
            None => { return true }
            Some(root) => {
                (root.left , root.right)
            }
        };
        self.is_symmetrical(l.borrow() , r.borrow() )
    }
    fn is_symmetrical(&self, left: &Option<Box<TreeNode>>, right: &Option<Box<TreeNode>>) -> bool {

        if left.is_none() && right.is_none() { return true; }
        if left.is_none() || right.is_none() { return false; }

        let isok_val = left.clone().unwrap().val == right.clone().unwrap().val;
        let isok_left = self.is_symmetrical(left.clone().unwrap().left.borrow() , right.clone().unwrap().right.borrow());
        let isok_right = self.is_symmetrical(left.clone().unwrap().right.borrow() , right.clone().unwrap().left.borrow());

        isok_left && isok_val && isok_right

    }
}


#[test]
fn test58_false() {
    let s = Solution::new();


    let l2_1 = Some(Box::new(TreeNode::new(21)));
    let l2_2 = Some(Box::new(TreeNode::new(22)));
    let l2_3 = Some(Box::new(TreeNode::new(23)));
    let l2_4 = Some(Box::new(TreeNode::new(24)));
    let l1_1 = Some(Box::new(TreeNode {
        val: 11,
        left: l2_1,
        right: l2_2
    }));

    let l1_2 = Some(Box::new(TreeNode {
        val: 12,
        left: l2_3,
        right: l2_4,
    }));

    let mut root = Some(Box::new(TreeNode {
        val: 1,
        left: l1_1,
        right: l1_2,
    }));


    let expext = false;

    let  result = s.isSymmetrical(root);
    assert_eq!(expext , result ) ;
}

#[test]
fn test58_true() {
    let s = Solution::new();


    let l2_1 = Some(Box::new(TreeNode::new(21)));
    let l2_2 = Some(Box::new(TreeNode::new(22)));
    let l2_3 = Some(Box::new(TreeNode::new(22)));
    let l2_4 = Some(Box::new(TreeNode::new(21)));
    let l1_1 = Some(Box::new(TreeNode {
        val: 11,
        left: l2_1,
        right: l2_2
    }));

    let l1_2 = Some(Box::new(TreeNode {
        val: 11,
        left: l2_3,
        right: l2_4,
    }));

    let mut root = Some(Box::new(TreeNode {
        val: 1,
        left: l1_1,
        right: l1_2,
    }));


    let expext = true;

    let  result = s.isSymmetrical(root);
    assert_eq!(expext , result ) ;
}
